<?php

define ('FORM_PATH', dirname(__FILE__) . '/');

require FORM_PATH . 'general.php';

class FormBuilder
{
	const GET  = 'get';  // Default (ref. W3C)
	const POST = 'post'; // Use Post for uploads.

	const ENCODE	= 'application/x-www-form-urlencoded'; // Default (ref. W3C)
	const MULTIPART = 'multipart/form-data'; // File uploads

	private $form = array ( 'action', 'method', 'enctype' );

#------------------------------------------------------------------------------

	/**
	 * Object constructor, will setup defaults or any paramters the user
	 * supplies at the time.
	 *
	 * @param mixed $action  URI for the agent to send its request.
	 * @param mixed $method  How the agent should send the request.
	 * @param mixed $enctype In what format is the request in.
	 */
	public function __construct ($action = null, $method = null, $enctype = null)
	{
		$this->form = array_fill_keys($this->form, null);

		// Let the set methods handle all the data handling. (DRY)
		$this->setAction($action);
		$this->setMethod($method);
		$this->setEnctype($enctype);
	}

#------------------------------------------------------------------------------

	# This will soon be refactored out to a second class.
	public function __toString ()
	{
		$format = '<form%s>%s</form>';

		$attrs = '';
		foreach ($this->form as $attr => $value) {
			$value = htmlentities($value, ENT_QUOTES, 'UTF-8');
			$attrs .= sprintf(' %s="%s"', $attr, $value);
		}

		$children = '';
		foreach (FormBuilder_Children::retriveObjects() as $child) {
			$children .= $child->render();
		}

		return sprintf($format, $attrs, $children);
	}

#------------------------------------------------------------------------------

	/**
	 * Magic __call method. Using it to reduce all the get interface as
	 * they just return a few paramerters. Also accepts render as a method.
	 *
	 * @param string $func	Function name.
	 * @param array  $args	Array of arguments like that of func_get_args().
	 * 
	 * @return mixed
	 */
	public function __call ($func, $args)
	{
		$func = defvalue(strtolower($func));

		if ($func) {
			if ($func === 'render') {
				return $this->__toString();
			}
			
			if (substr($func, 0, 3) === 'get') {
				$func = strpos($func, 3);
				if (isset($this->form[$func])) {
					return $this->form[$func];
				}
			}
		}

		return false;
	}

#------------------------------------------------------------------------------

	public function setAction ($action = null)
	{
		$action = defvalue($action, $_SERVER['PHP_SELF']);

		// If we have access to filter_var we will sanitize our url.
		// TODO: Emulate filter_var if it doesn't exist.
		if (function_exists('filter_var')) {
			$action = filter_var($action, FILTER_SANITIZE_URL);
		}

		$this->form['action'] = $action;
		return $this;
	}

	public function setMethod ($method = null)
	{
		$index  = array ( self::GET, self::POST );
		$method = defvalue(strtolower($method), self::GET);

		if (!in_array($method, $index)) {
			$error = 'Invalid method was given. Allowed: GET or POST; (Passed: %s)';
			$error = sprintf($error, $method);

			throw new FormBuilder_Exception($error, 102);
			return false;
		}

		$this->form['method'] = $method;
		return $this;
	}

	private function _checkEnctype ()
	{
		if ($this->form['enctype'] === self::MULTIPART) {
			if ($this->form['method'] !== self::POST) {
				$this->form['method'] = self::POST;

				$notice = 'Form method was changed to post due to the use of enctype multipart.';
				trigger_error($notice, E_USER_NOTICE);
			}
		}

		return $this;
	}

	public function setEnctype ($enctype = null)
	{
		$index = array ( 'encode' => self::ENCODE, 'multipart' => self::MULTIPART );
		$enctype = defvalue(strtolower($enctype), self::ENCODE);

		if (isset($index[$enctype])) {
			$this->form['enctype'] = $index[$enctype];
			return $this->_checkEnctype();
		}

		if (in_array($enctype, $index)) {
			$this->form['enctype'] = $enctype;
			return $this->_checkEnctype();
		}

		$error = 'Invalid enctype was given. Allowed application/x-www-form-urlencoded or multipart/form-data; (Passed: %s)';
		$error = sprintf($error, $enctype);

		throw new FormBuilder_Exception($error, 103);
		return false;
	}

#------------------------------------------------------------------------------

	public function addInput ($type = null, $name = null, $value = null, $attrs = null)
	{
		return new FormBuilder_Element_Input($type, $name, $value, $attrs);
	}

	public function addSelect () {}

	public function addTextArea () {}
}

